package at.ac.tuwien.dse.health.dashboard;

import at.ac.tuwien.dse.health.dashboard.dto.Notification;
import at.ac.tuwien.dse.health.dashboard.dto.SurgerySlotDTO;
import at.ac.tuwien.dse.health.entity.Doctor;
import at.ac.tuwien.dse.health.entity.Hospital;
import at.ac.tuwien.dse.health.entity.Patient;
import at.ac.tuwien.dse.health.entity.SurgerySlot;
import at.ac.tuwien.dse.health.reservation.ReservationCancellation;
import at.ac.tuwien.dse.health.reservation.ReservationRequest;
import at.ac.tuwien.dse.health.rest.RestController;
import at.ac.tuwien.dse.health.security.Secured;
import com.google.common.collect.ImmutableList;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static at.ac.tuwien.dse.health.dashboard.HealthService.MessageMappingFunction;
import static at.ac.tuwien.dse.health.dashboard.HealthService.SurgerySlotMappingFunction;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static org.apache.commons.lang3.time.DateUtils.addMinutes;

/**
 * @author Bernhard Nickel
 * @author Gregor Schauer
 * @author Dominik Strasser
 */
@RestController
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class HealthRestController {
	@Inject
	HealthService service;

	@RequestMapping("/slot")
	@ResponseBody
	@Secured
	public List<SurgerySlotDTO> list() {
		return transform(service.listSlots(null), new SurgerySlotMappingFunction());
	}

	@RequestMapping("/slot/create")
	@ResponseBody
	@Secured(Hospital.class)
	public SurgerySlotDTO create(@RequestParam("start") Date startDate, @RequestParam("end") Date endDate) {
		return new SurgerySlotMappingFunction().apply(service.createSlot(startDate, endDate));
	}

	@RequestMapping("/slot/createRepeated")
	@ResponseBody
	@Secured(Hospital.class)
	public List<SurgerySlotDTO> createRepeated(@RequestParam("start") Date startDate,
											   @RequestParam("duration") int duration,
											   @RequestParam(value = "times", defaultValue = "1") int times) {
		List<SurgerySlot> slots = new ArrayList<SurgerySlot>(times);
		for (int i = 0; i < times; ) {
			slots.add(service.createSlot(addMinutes(startDate, i * duration), addMinutes(startDate, ++i * duration)));
		}
		return transform(newArrayList(slots), new SurgerySlotMappingFunction());
	}

	@RequestMapping("/slot/delete")
	@ResponseBody
	@Secured(Hospital.class)
	public SurgerySlotDTO delete(@RequestParam long slotId) {
		return new SurgerySlotMappingFunction().apply(service.deleteSlot(slotId));
	}

	@RequestMapping("/slot/request")
	@ResponseBody
	@Secured(Doctor.class)
	public ReservationRequest requestReservation(@RequestParam("patient") int socialSecurityNumber,
												 @RequestParam("maxKilometers") int radius,
												 @RequestParam("surgeryType") String type) {
		return service.requestReservation(socialSecurityNumber, radius, type);
	}

	@RequestMapping("/slot/cancel")
	@ResponseBody
	@Secured(Doctor.class)
	public ReservationCancellation cancelReservation(@RequestParam("id") int slotId) {
		return service.cancelReservation(slotId);
	}

    @RequestMapping(value = "/hospital")
    @ResponseBody
	@Secured
    public List<String> getAvailableHospitals() {
		return ImmutableList.<String>builder().add("").addAll(service.getHospitalNames()).build();
	}

	@RequestMapping("/department")
	@ResponseBody
	@Secured
	public List<String> getTypes() {
		return ImmutableList.<String>builder().add("").addAll(service.getDepartmentNames()).build();
	}

	@RequestMapping("/patient/{socialSecurityNumber}")
	@ResponseBody
	@Secured(Doctor.class)
	public Patient getPatient(@PathVariable("socialSecurityNumber") Integer socialSecurityNumber) {
		return service.getPatient(socialSecurityNumber);
	}

	@RequestMapping("/message")
	@ResponseBody
	@Secured
	public List<Notification> getUnreadNotifications() {
		return transform(service.getUnreadMessages(), new MessageMappingFunction());
	}
}
